package com.ternnetwork.core.configuration.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.Predicate;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.ternnetwork.commons.model.http.BaseResponse;
import com.ternnetwork.commons.utils.ExtendedStringUtils;
import com.ternnetwork.core.configuration.dto.SeqQueryDto;
import com.ternnetwork.core.configuration.entity.Seq;
import com.ternnetwork.core.configuration.enums.SeqMessages;
import com.ternnetwork.core.configuration.repository.SeqRepository;
import com.ternnetwork.core.configuration.service.SeqService;

@Service
public class SeqServiceImpl implements SeqService {
	
	
	@Autowired
	private SeqRepository seqRepository;
	
	
	
	@Override
	public BaseResponse getOne(Long id) {
		
        BaseResponse  baseResponse=new BaseResponse();
		
        Seq t=seqRepository.getOne(id);
		
		baseResponse.setSccucess(t);
		
		return baseResponse;
	}

	@Override
	public BaseResponse add(Seq t) {
		
	    BaseResponse  baseResponse=checkProperties(t);
	    //校验不通过
	    if(baseResponse.getStatus().intValue()==0) {
	    	return baseResponse;
	    }
        
    	long totalCount=seqRepository.getCountByName(t.getName()); 
    	
      	if(totalCount>0L) {
    		baseResponse.setFailed(SeqMessages.FAILED_MESSAGE_NAME_CAN_NOT_BE_DUPLICATE.getName());
    		return baseResponse;
    	}
		
      	t.setName(t.getName().toUpperCase());
      	
		seqRepository.saveAndFlush(t);
		
		baseResponse.setSccucess(t);
		
		return baseResponse;
	}

	@Override
	public BaseResponse update(Seq t) {
		
		BaseResponse  baseResponse=checkProperties(t);
	    //校验不通过
	    if(baseResponse.getStatus().intValue()==0) {
	    	return baseResponse;
	    }
    	
    	long totalCount=seqRepository.getCountByNameAndExcludeId(t.getName(), t.getId()); 
    	
      	if(totalCount>0L) {
    		baseResponse.setFailed(SeqMessages.FAILED_MESSAGE_NAME_CAN_NOT_BE_DUPLICATE.getName());
    		return baseResponse;
    	}
    	
    	Seq old=seqRepository.getOne(t.getId());
    	
    	if(old==null||old.getId().longValue()==0L) {
    		baseResponse.setFailedForObjectNotExist();
    		return baseResponse;
    	}
    	
    	old.setName(t.getName().toUpperCase());
    	old.setAllocationSize(t.getAllocationSize());
    	old.setLength(t.getLength());
    	old.setNextValue(t.getNextValue());
    	old.setPrefix(t.getPrefix());
    	
      	seqRepository.saveAndFlush(old);
		baseResponse.setSccucess(t);
		return baseResponse;
	}

	@Override
	public BaseResponse findByPage(Pageable pageable, SeqQueryDto dto) {
		 
		 BaseResponse  baseResponse=new BaseResponse();
	    	
     	 Page<Seq> page = seqRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {

         List<Predicate> predicates = new ArrayList<>();

         if(!StringUtils.isEmpty(dto.getName())){
             predicates.add(criteriaBuilder.like(root.get("name").as(String.class),"%".concat(dto.getName()).concat("%")));
         }

         Predicate[] predicateArray = new Predicate[predicates.size()];

         return criteriaBuilder.and(predicates.toArray(predicateArray));
         
     }, pageable);
     	 
     	baseResponse.setSccucess(page);
    	
    	return baseResponse;
	}

	@Override
	public BaseResponse findAll(SeqQueryDto dto) {
		   
		 
   	    BaseResponse  baseResponse=new BaseResponse();
   	
    	List<Seq> itemList = seqRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {

        List<Predicate> predicates = new ArrayList<>();

        if(!StringUtils.isEmpty(dto.getName())){
            predicates.add(criteriaBuilder.like(root.get("name").as(String.class),"%".concat(dto.getName()).concat("%")));
        }

        Predicate[] predicateArray = new Predicate[predicates.size()];

        return criteriaBuilder.and(predicates.toArray(predicateArray));
    });
    	 
    	baseResponse.setSccucess(itemList);
   	
   	    return baseResponse;
	}

	@Override
	public BaseResponse deleteById(Long id) {
		
		BaseResponse  baseResponse=new BaseResponse();
		
		Seq old=seqRepository.getOne(id);
		
		if(old==null||old.getId().longValue()==0L) {
    		baseResponse.setFailedForObjectNotExist();
    		return baseResponse;
    	}
		if(old.getId().longValue()==1L) {
    		baseResponse.setFailed("不可删除该对象！");
    		return baseResponse;
    	}
		
		seqRepository.delete(old);
		
		baseResponse.setSccucess();
		
		return baseResponse;
	}
	@Override
	@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor=Exception.class)
	public String getNextValueBySeqName(String name){
		List<Seq> list=seqRepository.findAllAndLockByName(name);
		if(list.size()==0){
			return null;
		}
		String nextValue="";
		for(Seq t:list){
			nextValue=t.getPrefix()+ExtendedStringUtils.fillString(t.getLength(), String.valueOf(t.getNextValue()), "0");
			t.setNextValue(t.getNextValue()+t.getAllocationSize());
			seqRepository.saveAndFlush(t);
		}
		return nextValue;
	}
	
	
	 private BaseResponse checkProperties (Seq t) {
    	 
		    BaseResponse  baseResponse=new BaseResponse();
		    
		    if(StringUtils.isEmpty(t.getName())) {
		    	baseResponse.setFailed(SeqMessages.FAILED_MESSAGE_NAME_CAN_NOT_BE_EMPTY.getName());
		    	return baseResponse;
		    }
		    if(StringUtils.isEmpty(t.getPrefix())) {
		    	baseResponse.setFailed(SeqMessages.FAILED_MESSAGE_PREFIX_CAN_NOT_BE_EMPTY.getName());
		    	return baseResponse;
		    }
		
		    if(t.getAllocationSize().longValue()<=0L) {
		    	baseResponse.setFailed(SeqMessages.FAILED_MESSAGE_ALLOCATION_SIZE_MUST_BE_MORE_THAN_0.getName());
		    	return baseResponse;
		    }
		    if(t.getLength().intValue()<=0) {
		    	baseResponse.setFailed(SeqMessages.FAILED_MESSAGE_LENGTH_MUST_BE_MORE_THAN_0.getName());
		    	return baseResponse;
		    }
		    
		    if(t.getNextValue().longValue()<=0L) {
		    	baseResponse.setFailed(SeqMessages.FAILED_MESSAGE_NEXT_VALUE_MUST_BE_MORE_THAN_0.getName());
		    	return baseResponse;
		    }
		    
		    baseResponse.setSccucess();
		    return baseResponse;
   }

}
